package com.xm.lock.sad;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 数据库悲观锁 √
 * 原理：
 *   在数据库层面，可以通过 SELECT ... FOR UPDATE 实现悲观锁。
 *   这种方式会锁定查询到的数据行，直到事务提交或回滚。
 * 特点：
 *   适用于分布式系统中的数据一致性控制。
 *   锁的粒度较细，但性能较低。
 */
public class TestSelectForUpdate03 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement statement = null;
        try {
            //1、注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2、创建数据库连接
            String url = "jdbc:mysql://127.0.0.1:3306/huakaiyoushi?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&allowMultiQueries=true&rewriteBatchedStatements=true";
            String username = "root";
            String password = "123456";
            conn = DriverManager.getConnection(url, username, password);
            //3、开启事务/取消事务自动提交
            conn.setAutoCommit(false);
            statement = conn.prepareStatement("SELECT *FROM books WHERE id = 1 FOR UPDATE ");
            statement.executeQuery();

            statement = conn.prepareStatement("UPDATE books SET price = price + 1 WHERE id = 1 ");
            statement.executeUpdate();

            conn.commit();
        } catch (ClassNotFoundException | SQLException e) {
            if(conn != null){
                try {
                    conn.rollback();
                } catch (SQLException ignored) {
                }
            }
            throw new RuntimeException(e);
        } finally {
            if(statement != null){
                try {
                    statement.close();
                } catch (SQLException ignored) {
                }
            }
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException ignored) {
                }
            }
        }
    }
}
